package com.fingard.dsp.bank.directbank.boc11;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.directbank.gzdsf01.util.CfbsAPI;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.text.StringHelper;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 中国银行银保通(BOC11)批量代收付
 */
public class BOC11BatPayRec extends BOC11Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        return d_BatPayRec(p_req1988);
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        return d_QryBatPayRec(p_req1998);
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return d_BatPayRec(p_req9188);
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return d_QryBatPayRec(p_req9198);
    }

    public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
        retAts.reqSeqID = p_reqBat.reqBatchNO;

        FtpPortClient ftpPortClient = null;

        try {
            // 代收付文件内容
            StringBuilder sbFileContent = new StringBuilder();

            /* BPS商户号 */
			if (StringHelper.isNullOrEmpty(bankFront.serverCode)) {
				retAts.respCode = "0";
				retAts.respInfo = "BPS业务类型为空,请检查'config/BankFront.xml'中'serverCode'配置节点信息!";
				retAts.reqSeqID = p_reqBat.reqBatchNO;
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = FailCode.E9981;
				retAts.writeRetToATS();
				return retAts;
			}
			sbFileContent.append(String.format("%-8s", bankFront.serverCode));

            /* BPS业务类型：C1 - 行内代付，C2 - 跨行代付(小额定期贷记），C3 - 跨行代付(普通贷记)，D1 - 行内代收 */
			String busiType = "C1";
			if (p_reqBat.reqHeader.isBatRec) {
                busiType = "D1";
            }
			sbFileContent.append(busiType);

            /* 批次号(与文件名中批次号的后3位保持一致) */
			sbFileContent.append(p_reqBat.reqBatchNO.substring(p_reqBat.reqBatchNO.length() - 3));

            /* 保险公司收款账号或付款账号 */
			sbFileContent.append(String.format("%-25s", p_reqBat.ownAct));

            /* 总金额 */
			sbFileContent.append(String.format("%15s", p_reqBat.totalAmt).replace(" ", "0"));

            /* 总笔数 */
			sbFileContent.append(String.format("%8s", p_reqBat.totalNum).replace(" ", "0"));

            /* 业务摘要 */
			sbFileContent.append("EB");

            /* 币种 */
			sbFileContent.append("CNY");

            /* 加密标识 */
			sbFileContent.append("00");

            /* 文本版本号 */
			sbFileContent.append("00000001");

            /* 汇划流水号 */
			sbFileContent.append(String.format("%-32s", ""));

            /* 汇划日期 */
			sbFileContent.append(String.format("%-8s", ""));

            /* 退划流水号 */
			sbFileContent.append(String.format("%-32s", ""));

            /* 退划日期 */
			sbFileContent.append(String.format("%-8s", ""));

            /* 成功总金额 */
			sbFileContent.append(String.format("%-15s", "").replace(" ", "0"));

            /* 成功总笔数 */
			sbFileContent.append(String.format("%-8s", ""));

            /* 失败总金额 */
			sbFileContent.append(String.format("%-15s", "").replace(" ", "0"));

            /* 失败总笔数 */
			sbFileContent.append(String.format("%-8s", ""));

            /* 结束标识 */
			sbFileContent.append("|\n");

            // 文件明细
            while (p_reqBat.readRecord()) {
                StringBuilder tmpReqBodyDetail = new StringBuilder();

                /* 流水号 */
                tmpReqBodyDetail.append(String.format("%-30s", p_reqBat.readedDetail.askNumber));

                String oppAct = "";
                String oppName = "";
                if ("1988".equals(p_reqBat.reqHeader.transType)) {
                    oppAct = p_reqBat.readedDetail.recAct;
                    oppName = p_reqBat.readedDetail.recName;
                } else {
                    oppAct = p_reqBat.readedDetail.payAct;
                    oppName = p_reqBat.readedDetail.payName;
                }

                /* 账号 */
                tmpReqBodyDetail.append(String.format("%-25s", oppAct));

                /* 账号名称 */
                tmpReqBodyDetail.append(CfbsAPI.rightFill(oppName, 58, " "));

                /* 省行标识 */
                tmpReqBodyDetail.append(String.format("%-14s", ""));

                /* 收款行人行行号 */
                tmpReqBodyDetail.append(String.format("%-14s", p_reqBat.readedDetail.cnapsCode));

                /* 证件类型 */
                tmpReqBodyDetail.append(String.format("%-2s", convertCertTypeToBank(p_reqBat.readedDetail.certType)));

                /* 证件号码 */
                tmpReqBodyDetail.append(String.format("%-32s", p_reqBat.readedDetail.certNum));

                /* 备注 */
                tmpReqBodyDetail.append(String.format("%-80s", CfbsAPI.rightFill(p_reqBat.readedDetail.memo, 58, " ")));

                /* 投保单号 */
                tmpReqBodyDetail.append(String.format("%-30s", p_reqBat.readedDetail.insuPolicyNum));

                /* 保单号 */
                tmpReqBodyDetail.append(String.format("%-30s", p_reqBat.readedDetail.sourceNoteCode));

                /* 投保人姓名 */
                tmpReqBodyDetail.append(CfbsAPI.rightFill(oppName, 120, " "));

                /* 金额 */
				tmpReqBodyDetail.append(String.format("%15s", p_reqBat.readedDetail.payAmount).replace(" ", "0"));

                String detailBusiType = getBankConfig().getValueAsString("busiType");
                if (StringHelper.hasAnyChar(detailBusiType)) {
                    detailBusiType = getBankConfig().getMapValueByKey("busiTypeMapping", p_reqBat.readedDetail.srcXElement.getSingleText(detailBusiType));
                }
                /* 保险业务类型 */
				if (StringHelper.isNullOrEmpty(detailBusiType)) {
					retAts.respCode = "0";
					retAts.respInfo = "保险业务类型代码为空,请检查'config/portfiles/BOC11/config.xml'中'busiType'配置节点信息!";
					retAts.reqSeqID = p_reqBat.reqBatchNO;
					retAts.transState = PaymentState.FAIL_Batch;
					retAts.payInfoCode = FailCode.E9981;
					retAts.writeRetToATS();
					return retAts;
				}
                tmpReqBodyDetail.append(detailBusiType);

                /* 保险业务描述 */
                tmpReqBodyDetail.append(CfbsAPI.rightFill(p_reqBat.readedDetail.useType, 20, " "));

                /* 中行出单标志：0-非中行出单，1-中行出单 */
                tmpReqBodyDetail.append("1");

				/* 保险业务详情 */
				tmpReqBodyDetail.append(String.format("%-60s", ""));

				/* 备用 */
				tmpReqBodyDetail.append(String.format("%-140s", ""));

                /* 保险公司摘要 */
                tmpReqBodyDetail.append(String.format("%-100s", ""));

                /* 冲正状态 */
                tmpReqBodyDetail.append(" ");

                /* 冲正交易核心返回码 */
                tmpReqBodyDetail.append(String.format("%-8s", ""));

                /* 冲正交易核心返回信息 */
                tmpReqBodyDetail.append(String.format("%-80s", ""));

                /* 实扣金额 */
                tmpReqBodyDetail.append(String.format("%-15s", ""));

                /* 结束标识 */
                tmpReqBodyDetail.append("|\n");
                sbFileContent.append(tmpReqBodyDetail);
            }
            WriteBankLogLn2("批次请求文件内容:\r\n" + sbFileContent.toString());

            // 上传文件保存本地: 保险公司代码-BPS业务类型-日期-批次号-签约行机构号.DAT
			if (StringHelper.isNullOrEmpty(bankFront.corpNo) || bankFront.corpNo.length() != 4) {
				retAts.respCode = "0";
				retAts.respInfo = "保险公司代码为空或长度非4位,请检查'config/BankFront.xml'中'corpNo'配置节点信息!";
				retAts.reqSeqID = p_reqBat.reqBatchNO;
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = FailCode.E9981;
				retAts.writeRetToATS();
				return retAts;
			}
			String bankOrg = getBankConfig().getMapValueByKey("bankOrgMapping", p_reqBat.ownAct);
			if (StringHelper.isNullOrEmpty(bankOrg)) {
				retAts.respCode = "0";
				retAts.respInfo = "保险公司账户" + p_reqBat.ownAct + "签约行机构号为空,请检查'config/portfiles/BOC11/config.xml'中'bankOrgMapping'配置节点信息!";
				retAts.reqSeqID = p_reqBat.reqBatchNO;
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = FailCode.E9981;
				retAts.writeRetToATS();
				return retAts;
			}
			bankOrg = String.format("%5s", bankOrg).replace(" ", "0");
			if (p_reqBat.reqBatchNO.length() > 8) {
                retAts.respCode = "0";
                retAts.respInfo = "批次号长度应该为8位,实际长度为:" + p_reqBat.reqBatchNO.length() + ",请设置'流水号长度'银行参数!";
                retAts.reqSeqID = p_reqBat.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }
            String tmpPaySendDate = Format.Date8Format.format(p_reqBat.getPayDateTime());
            String tmpUploadFileName = bankFront.corpNo + "-" + busiType + "-" + tmpPaySendDate + "-" + p_reqBat.reqBatchNO + "-" + bankOrg + ".DAT";
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + tmpUploadFileName;
            WriteBankLogLn2("批次请求文件保存本机路径: " + tmpLocalMarkPath);

            if (FileHelper.existFile(tmpLocalMarkPath)) {
                retAts.respCode = "0";
                retAts.respInfo = "本地批次文件[" + tmpLocalMarkPath + "]已上传,请勿重复上传!";
                retAts.reqSeqID = p_reqBat.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }
            FileHelper.writeFile(tmpLocalMarkPath, sbFileContent.toString(), getCharset());

            // 批次映射文件写入本地
            StringBuilder tmpSeqNoContent = new StringBuilder();
            tmpSeqNoContent.append(tmpUploadFileName);
            WriteBankLogLn2("批次映射文件内容:\r\n" + tmpSeqNoContent.toString());
            String tmpLocalMappingFile = getDataFileDirectory(p_reqBat.getPayDateTime()) + File.separator + p_reqBat.reqBatchNO + ".txt";
            WriteBankLogLn2("批次映射文件本地保存路径:\r\n" + tmpLocalMappingFile);
            FileHelper.writeFile(tmpLocalMappingFile, tmpSeqNoContent.toString(), getCharset());

            // 上送银保通服务器
            FtpSet ftpSet = bankFront.getFtpSet("bat");
            ftpPortClient = new FtpPortClient(ftpSet);
            String ftpFilePath = StringHelper.trimEnd(ftpSet.upDir, "/") + "/" + tmpUploadFileName;
            WriteBankLogLn("待上传FTP服务器请求文件路径:" + ftpFilePath);
            FtpReceiver ftpReceiver = ftpPortClient.uploadFile(tmpLocalMarkPath, ftpFilePath);

            retAts.respCode = "0";
            if (!ftpReceiver.isCompleted) {
                retAts.respCode = "-1";
                retAts.respInfo = ftpReceiver.connMsg;
            } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
                retAts.respInfo = "上传失败";
                retAts.transState = "BatchFailed";
                retAts.payInfoCode = "E9999";
            } else {
                retAts.respInfo = "上传成功";
                retAts.transState = "Uploaded";
                retAts.payInfoCode = "I4001";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        } finally {
            if (ftpPortClient != null) {
                ftpPortClient.disconnect();
            }
        }

        retAts.writeRetToATS();
        return retAts;
    }

    public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
        retAts.reqSeqID = p_reqQryBat.reqBatchNO;

        FtpPortClient ftpPortClient = null;

        try {
            String tmpDownFileName = "";
            String tmpLocalMappingFile = getDataFileDirectory(p_reqQryBat.getBgnDateTime()) + File.separator + p_reqQryBat.reqBatchNO + ".txt";
            if (new File(tmpLocalMappingFile).exists()) {
                tmpDownFileName = FileHelper.readFileText(tmpLocalMappingFile, getCharset());
            } else {
				retAts.respCode = "-1";
				retAts.respInfo = "本机批次映射文件[" + tmpLocalMappingFile + "]未生成,请人工排查当前文件是否存在!";
				retAts.writeAfterDetail();
				return retAts;
			}
            tmpDownFileName = tmpDownFileName.replace(".DAT", "");

            FtpSet ftpSet = bankFront.getFtpSet("bat");
            ftpPortClient = new FtpPortClient(ftpSet);
            FtpReceiver ftpReceiver = ftpPortClient.listFiles(ftpSet.downDir);
            if (!ftpReceiver.isCompleted) {
                retAts.respCode = "-1";
                if (ConnState.FILE_NOT_EXISTS.equals(ftpReceiver.connState)) {
                    retAts.respInfo = "FTP服务器批次结果文件尚未生成!";
                } else {
                    retAts.respInfo = "遍历目录:" + ftpSet.downDir + "失败!";
                }
                retAts.writeAfterDetail();
                return retAts;
            }

            List<String> fileNameList = Arrays.asList(ftpReceiver.connMsg.split(","));
            Iterator<String> iterator = fileNameList.iterator();
            while (iterator.hasNext()) {
                String ftpFileName = ((String) iterator.next()).toString();
                if (ftpFileName.contains(tmpDownFileName)) {
                    tmpDownFileName = ftpFileName;
                }
            }

            // 下载文件保存本地: 保险公司代码+BPS业务类型+日期+批次号+签约行机构号.RET
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + tmpDownFileName;
            WriteBankLogLn2("批次结果文件保存本机路径: " + tmpLocalMarkPath);

            String ftpFilePath = StringHelper.trimEnd(ftpSet.downDir, "/") + "/" + tmpDownFileName;
            WriteBankLogLn2("待下载FTP服务器结果文件路径:\r\n" + ftpFilePath);
            ftpReceiver = ftpPortClient.downloadFile(tmpDownFileName, tmpLocalMarkPath);
            if (ftpReceiver.isCompleted) {
                String tmpStrRet = FileHelper.readFileText(tmpLocalMarkPath, getCharset());
                WriteBankLogLn2("本地批次结果文件内容:\r\n" + tmpStrRet);

				if (StringHelper.hasAnyChar(tmpStrRet)) {
					retAts.respCode = "0";
					retAts.reqSeqID = p_reqQryBat.reqBatchNO;

					StringReader strReader = new StringReader(tmpStrRet);
					BufferedReader tmpReader = new BufferedReader(strReader);
					String totalHeadMsg = tmpReader.readLine();
					if (tmpDownFileName.endsWith(".ERR")) {
						retAts.transState = PaymentState.FAIL_Batch;
						retAts.payInfoCode = totalHeadMsg.substring(0, 8);
						retAts.respInfo = totalHeadMsg.substring(8).replace("\n","");
						retAts.writeAfterDetail();
						return retAts;
					}

					while (true) {
						String eachline = tmpReader.readLine();
						if (StringHelper.isNullOrEmpty(eachline)) {
							break;
						}

						RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
						byte[] eachBytes = eachline.getBytes(getCharset());
						if ("1998".equals(p_reqQryBat.reqHeader.transType)) {
							tmpRetDetail.recAct = new String(eachBytes, 30, 25, getCharset()).trim();
							tmpRetDetail.recName = new String(eachBytes, 55, 58, getCharset()).trim();
						} else {
							tmpRetDetail.payAct = new String(eachBytes, 30, 25, getCharset()).trim();
							tmpRetDetail.payName = new String(eachBytes, 55, 58, getCharset()).trim();
						}
                        tmpRetDetail.payAmount = Format.DecimalAmtFormat.format(Double.parseDouble(new String(eachBytes, 435, 15, getCharset())));
						tmpRetDetail.postScript = eachline.substring(0, 30).trim();
						String resultInfo = eachline.split("\\|")[1];
						tmpRetDetail.result = resultInfo.substring(0,1);
						tmpRetDetail.payInfoCode = resultInfo.substring(1,9).trim();
						tmpRetDetail.memo = resultInfo.substring(9).trim();

						retAts.writeRetDetail(tmpRetDetail);
					}
				} else {
					retAts.respCode = "-1";
					retAts.respInfo = "本地批次结果文件内容为空!";
				}
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "批次结果文件下载失败:" + ftpReceiver.connMsg;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        } finally {
            if (ftpPortClient != null) {
                ftpPortClient.disconnect();
            }
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}